//
//  ZMTools.m
//  demo
//
//  Created by chenzm on 2018/8/17.
//  Copyright © 2018年 chenzm. All rights reserved.
//

#import "ZMTools.h"
#import <objc/runtime.h>


@implementation ZMTools

/**
 修改某个私有属性
 @param className 初始化的类对象
 @param keyArr 要更改的属性值数组
 @param valueArr 更改后的属性值
 @param isLog 是否打印输出日志
 */
+(BOOL)zm_modifyClassIvar:(id)className keyArr:(NSArray *)keyArr valueArr:(NSArray *)valueArr isLog:(BOOL)isLog{
    unsigned int count = 0;
    // 动态获取类中的所有属性(包括私有)
    Ivar *ivar = class_copyIvarList([className class], &count);
    
    if (keyArr&&valueArr&&keyArr.count == valueArr.count) {
        // 遍历属性找到对应字段
        for (int i = 0; i < count; i ++) {
            Ivar tempIvar = ivar[i];
            //ivar_getName:将IVar变量转化为字符串
            const char *varChar = ivar_getName(tempIvar);
            NSString *varString = [NSString stringWithUTF8String:varChar];
            
            if(isLog == YES){
                //ivar_getTypeEncoding：获取IVar的类型
                const char *typeChar = ivar_getTypeEncoding(tempIvar);
                NSString *typeString = [NSString stringWithUTF8String:typeChar];
                NSLog(@"\n👺👺👺\ntype:%@\nname:%@",typeString,varString);
            }
            
            for (NSInteger i = 0; i < keyArr.count; i++) {
                NSString *keyStr = keyArr[i];
                NSString *valStr = valueArr[i];
                if (keyStr&&valStr&&keyStr.length > 0) {
                    if ([varString isEqualToString:keyStr]) {
                        object_setIvar(className, tempIvar, valStr);
                    }
                }
            }
        }
        return YES;
    }else{
        return NO;
    }
}

///获得类的所有私有方法
+ (void)zm_searchClassMethod:(id)className isLog:(BOOL)isLog{
    unsigned int count = 0;
    //所有在.m文件显式实现的方法都会被找到
    
    //Method：runtime声明的一个宏，表示一个方法
    //class_copyMethodList：获取所有方法
    Method *memberFuncs = class_copyMethodList([className class], &count);
    for (int i = 0; i < count; i++) {
        //method_getName：读取一个Method类型的变量，输出我们在上层中很熟悉的SEL
        SEL name = method_getName(memberFuncs[i]);
        NSString *methodName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
        if (isLog == YES) {
            NSLog(@"\n😜😜😜method:\n%@", methodName);
        }
    }
    
}


///获取文件地址
+(NSString *)getDomainsPathWithFile:(NSString *)fileStr{
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
    path = [path stringByAppendingPathComponent:fileStr];
    return path;
}

///拦截替换方法
+ (BOOL)zm_swizzleMethod:(SEL)origSel withMethod:(SEL)aftSel {
    Method originMethod = class_getInstanceMethod(self, origSel);
    Method newMethod = class_getInstanceMethod(self, aftSel);
    if(originMethod && newMethod) {//必须两个Method都要拿到
        if(class_addMethod(self, origSel, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
            //实现成功添加后
            class_replaceMethod(self, aftSel, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
        }
        return YES;
    }
    return NO;
}

@end
